#include <stdlib.h>
#include "zyf_intmath.h"

/**
 * Desc: 简单的整形数学函数
 * Auth: 张宇飞
 * Date: 2015-09-14    
 */

// 0-90度的正弦表。正弦结果均x1000
static int deg90sin1000[] = {
0, 17, 34, 52, 69, 87, 104, 121, 139, 156, 173, 190, 207, 224, 241, 258, 275, 292, 309, 
325, 342, 358, 374, 390, 406, 422, 438, 453, 469, 484, 499, 515, 529, 544, 559, 573, 587, 
601, 615, 629, 642, 656, 669, 681, 694, 707, 719, 731, 743, 754, 766, 777, 788, 798, 809, 
819, 829, 838, 848, 857, 866, 874, 882, 891, 898, 906, 913, 920, 927, 933, 939, 945, 951, 
956, 961, 965, 970, 974, 978, 981, 984, 987, 990, 992, 994, 996, 997, 998, 999, 999, 1000
};

// 1-89度正切表。正切结果均x1000
static int deg89tan1000[] = {
17, 34, 52, 69, 87, 105, 122, 140, 158, 176, 194, 212, 230, 249, 267, 286, 305, 324, 344, 363, 383, 
404, 424, 445, 466, 487, 509, 531, 554, 577, 600, 624, 649, 674, 700, 726, 753, 781, 809, 839, 869, 
900, 932, 965, 999, 1035, 1072, 1110, 1150, 1191, 1234, 1279, 1327, 1376, 1428, 1482, 1539, 1600, 1664, 
1732, 1804, 1880, 1962, 2050, 2144, 2246, 2355, 2475, 2605, 2747, 2904, 3077, 3270, 3487, 3732, 4010,
4331, 4704, 5144, 5671, 6313, 7115, 8144, 9514, 11430, 14300, 19081, 28636, 57289
};

#define DEG89_ARR_LEN	(sizeof(deg89tan1000) / sizeof(deg89tan1000[0]) - 1)
/*********************| static functions |*********************/
static int normalize180(int d)
{
	if (d >= 360 || d < 0)
		d -= d / 360 * 360;
	if (d > 180)
		d -= 360;
	return d;
}

// 二分查找tan值
static void bsearchtan(int n, int l, int r, int* mint)
{
	int ll = r - l;
	if (ll < 1) {
		return;
	} else if (1 == ll) {
		mint[1] = mint[2];
		return;
	} else {
		ll = ll / 2 + l;
	}
	int k = deg89tan1000[ll] - n;
	int abk = (k > 0) ? k : -k;
	if ((mint[0] < 0) || (k < mint[0])) {
		mint[0] = abk;
		mint[1] = ll;
	}
	if (abk < 10) {
		return;
	} else if (k > 0) {
		mint[2] = l;
		bsearchtan(n, l, ll, mint);
	} else {
		mint[2] = r;
		bsearchtan(n, ll, r, mint);
	}
}

/*********************| extern functions |*********************/
int zyf_sin1000(int deg)
{
	deg = normalize180(deg);
	if (deg > 90)
		return deg90sin1000[180 - deg];
	else if (deg >= 0)
		return deg90sin1000[deg];
	else if (deg < -90)
		return -deg90sin1000[deg + 180];
	else
		return -deg90sin1000[-deg];
}

int zyf_cos1000(int deg)
{
	// 转换成正弦求出结果	
	deg = normalize180(deg);
	if (deg > 90)
		return -deg90sin1000[deg- 90];
	else if (deg>= 0) 
		return deg90sin1000[90 - deg];
	else if (deg< -90)
		return -deg90sin1000[-90 - deg];
	else
		return deg90sin1000[90 + deg];
}

int zyf_atan(int y, int x)
{
	if (0 == y)
		return (x < 0) ? 180 : 0;
	else if (0 == x)
		return (y > 0) ? 90 : -90;
	else {
		// 执行2分查找，记录差值最小的位置
		int mint[3] = {-1, 0, 0};
		int n = y * 1000 / x;
		if (n < 0)
			n = -n;
		bsearchtan(n, 0, DEG89_ARR_LEN, mint);
		// 象限转换
		++mint[1];
		if (y > 0)
			return (x > 0) ? mint[1] : -mint[1];
		else
			return -mint[1] - ((x > 0) ? 0 : 90);
	}
}
